using System;
using System.Windows.Forms;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Text;
using System.Text.RegularExpressions;
using System.IO;
using System.Xml;
using ManagedWinapi.Windows;
using DOMercury.Items;
using DOMercury.Interfaces;


namespace DOMercury.Managers            
{
    static class AutoCompleteManager
    {
        private static bool SMARTSEARCH = ConfigurationManager.SmartSearch;
        private static int MATCHLIM = ConfigurationManager.MaxResults;
        private static bool SearchOn;
        private static IndexStack istack;
        private static ItemStack itstack;
        private static StringStack sstack;
        private static List<TextItem> history;
        private static List<StartMenuItem> smlist;
        private static List<IItem> index;
        private static List<IItem> currentIndex;
        private static AutoCompleteStringCollection Params;
        //private static List<SystemWindowItem> windows;
        public static bool SmartSearch
        {
            get
            {
                return SMARTSEARCH;
            }
            set
            {
                SMARTSEARCH = value;
            }
        }

        public static int MaximumResults
        {
            get
            {
                return MATCHLIM;
            }
            set
            {
                MATCHLIM = value;
            }
        }
        public static void Load()
        {
            SearchOn = true;
            history = new List<TextItem>();
            Params = new AutoCompleteStringCollection();
            try
            {
                ReadItems(ref history);
            }
            catch (FileNotFoundException ex)
            {
                MessageBox.Show("Could Not find \"AutoComplete.xml\". Unable to load text items history.", "Error, Unable to find AutoComplete.xml", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
            catch (Exception ex)
            {
                MessageBox.Show("\"AutoComplete.xml\" is corrupt or damaged, or possibly in an incorrect format. Unable to load items history.", "Error, Unable to read AutoComplete.xml", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
            history.Sort();
            index = new List<IItem>();
            istack = new IndexStack(index);
            itstack = new ItemStack();
            sstack = new StringStack();     
            BuildIndex();
            currentIndex = index;
            
            //CreateSendToList();
        }

        #region Index Management Functions
        private static void BuildIndex()
        {
            List<IItem> nindex = new List<IItem>();
            //foreach (IItem i in AliasManager.AliasList)
            //{
            //    nindex.Add(i);
            //}
            BuildSMList();
            foreach (IItem i in smlist)
            {
                nindex.Add(i);
            }
            nindex.Add(new CurrentWindowItem());
            nindex.Add(new ScreenSaverItem());
            nindex.Add(new MyComputerItem());
            nindex.Add(new DeskTopItem());
            nindex.Add(new OptionsItem());
            nindex.Add(new RefreshItem());
            nindex.Add(new ExitItem());
            
            foreach (IItem i in history)
            {
                nindex.Add(i);
            }
            nindex.Sort();
            if (currentIndex == index)
            {
                index = nindex;
                istack.ResetBase(index);
                currentIndex = index;
            }
            else
            {
                index = nindex;
                istack.ResetBase(index);
            }
            
            BuildIcons(true);
        }

        private static void IndexPlugins()
        {
            System.ComponentModel.BackgroundWorker bw = new System.ComponentModel.BackgroundWorker();
            bw.DoWork += new System.ComponentModel.DoWorkEventHandler(bwPlugins_DoWork);
            bw.RunWorkerCompleted += new System.ComponentModel.RunWorkerCompletedEventHandler(bw_RunWorkerCompleted);
            bw.RunWorkerAsync();
        }

        static void bw_RunWorkerCompleted(object sender, System.ComponentModel.RunWorkerCompletedEventArgs e)
        {
            BuildIcons(false);
        }

        static void bw_RunWorkerPCompleted(object sender, System.ComponentModel.RunWorkerCompletedEventArgs e)
        {
            IndexPlugins();
        }

        private static void bwPlugins_DoWork(object sender, System.ComponentModel.DoWorkEventArgs e)
        {
            pIndexPlugins();
        }

        private static void pIndexPlugins()
        {
            foreach (IItemProvider p in PluginManager.ItemProviders)
            {
                index.AddRange(p.Items);
            }
        }

        private static void BuildIcons(bool plugs)
        {
            System.ComponentModel.BackgroundWorker bw = new System.ComponentModel.BackgroundWorker();
            bw.DoWork += new System.ComponentModel.DoWorkEventHandler(bwIcon_DoWork);
            if (plugs)
            {
                bw.RunWorkerCompleted += new System.ComponentModel.RunWorkerCompletedEventHandler(bw_RunWorkerPCompleted);
            }
            bw.RunWorkerAsync();
        }

        private static void bwIcon_DoWork(object sender, System.ComponentModel.DoWorkEventArgs e)
        {
            pBuildIcons();
        }

        private static void pBuildIcons()
        {
            foreach (IItemProvider p in PluginManager.ItemProviders)
            {
                try
                {
                    foreach (IconPair i in p.CustomIcons)
                    {
                        IconManager.AddCustomIcon(i.Key, i.Icon);
                    }
                }
                catch
                {

                }
            }
            

            foreach (IItem i in index)
            {
                IconManager.AddIcon(i.DisplayDesc);
            }
            foreach (Alias a in AliasManager.AliasList)
            {
                try
                {
                    IconManager.AddCustomIcon(a.DisplayDesc, System.Drawing.Icon.ExtractAssociatedIcon(a.Path).ToBitmap());
                }
                catch
                {
                }
            }
        }

        private static void BuildSMList()
        {
            
            List<StartMenuItem> tsmlist = new List<StartMenuItem>();
            DirectoryInfo di;
            //if Vista
            if (System.Environment.OSVersion.Version.Major == 6)
            {
                di = new DirectoryInfo(System.Environment.GetEnvironmentVariable("ALLUSERSPROFILE") + @"\Microsoft\Windows\Start Menu");
            }
            //else if xp
            else
            {
                di = new DirectoryInfo(System.Environment.GetEnvironmentVariable("ALLUSERSPROFILE") + @"\Start Menu");
            }
            FileInfo[] links = di.GetFiles("*.lnk", SearchOption.AllDirectories);

            foreach (FileInfo f in links)
            {
                tsmlist.Add(new StartMenuItem(f.FullName, Path.GetFileNameWithoutExtension(f.Name)));
            }

            links = di.GetFiles("*.url", SearchOption.AllDirectories);
            foreach (FileInfo f in links)
            {
                tsmlist.Add(new StartMenuItem(f.FullName, Path.GetFileNameWithoutExtension(f.Name)));
            }

            di = new DirectoryInfo(System.Environment.GetFolderPath(Environment.SpecialFolder.StartMenu));
            links = di.GetFiles("*.lnk", SearchOption.AllDirectories);
            foreach (FileInfo f in links)
            {
                tsmlist.Add(new StartMenuItem(f.FullName, Path.GetFileNameWithoutExtension(f.Name)));
            }
            links = di.GetFiles("*.url", SearchOption.AllDirectories);
            foreach (FileInfo f in links)
            {
                tsmlist.Add(new StartMenuItem(f.FullName, Path.GetFileNameWithoutExtension(f.Name)));
            }
            tsmlist.Sort();
            smlist = tsmlist;
        }

        public static void RefreshAliases()
        {
            RebuildIndex();
        }

        public static void RebuildIndex()
        {
            System.ComponentModel.BackgroundWorker bw = new System.ComponentModel.BackgroundWorker();
            bw.DoWork += new System.ComponentModel.DoWorkEventHandler(bw_DoWork);
            bw.RunWorkerAsync();
        }

        static void bw_DoWork(object sender, System.ComponentModel.DoWorkEventArgs e)
        {
            BuildIndex();
        }

        #endregion
        #region History Management Functions
        private static void ReadItems(ref List<TextItem> items)
        {
            XmlTextReader r = new XmlTextReader(new FileStream(Path.GetDirectoryName(Application.ExecutablePath) + "\\AutoComplete.xml", FileMode.Open, FileAccess.Read));
            while ((!r.EOF) && r.Name.Trim().CompareTo("Items") != 0)
            {
                r.Read();
            }
            r.Read();
            //r.Read();
            //r.Read();
            while ((!r.EOF) && r.Name.Trim().CompareTo("Items") != 0)
            {
                if (r.NodeType == XmlNodeType.EndElement)
                {
                    r.Read();
                }
                else
                {
                    switch (r.Name.Trim())
                    {
                        case "Item":
                            items.Add(new TextItem(ReadItem(r)));
                            r.Skip();
                            break;
                        case "Param":
                            Params.Add(ReadItem(r));
                            r.Skip();
                            break;
                        case "":
                            r.Read(); break;
                        default:
                            r.Skip(); break;
                    }
                }
            }
            r.Close();
        }

        private static string ReadItem(XmlTextReader r)
        {
            return r.GetAttribute("Value");
        }

        public static void AddToItemHistory(TextItem item)
        {
            if (item.Text.ToLower() != "current window")
            {
                if (!(item.Text.Length < 2))
                {
                    if (!history.Contains(item))
                    {
                        if (!((item.Text[1] == ':') && (item.Text.Length < 4)))
                        {
                            history.Add(item);
                            Save();
                        }
                    }
                }
            }
        }

        public static void AddToParamHistory(string param)
        {
            
                if (!(param.Length < 2))
                {
                    if (!Params.Contains(param))
                    {
                        if (!((param[1] == ':') && (param.Length < 4)))
                        {
                            Params.Add(param);
                            Save();
                        }
                    }
                }
            
        }

        private static void Save()
        {
            XmlTextWriter w = new XmlTextWriter(new StreamWriter(Path.GetDirectoryName(Application.ExecutablePath) + "\\AutoComplete.xml", false, Encoding.UTF8));
            w.WriteStartElement("Items");
            foreach (TextItem s in history)
            {
                w.WriteStartElement("Item");
                w.WriteAttributeString("Value", s.Text);
                w.WriteEndElement();
            }
            foreach (string s in Params)
            {
                w.WriteStartElement("Param");
                w.WriteAttributeString("Value", s);
                w.WriteEndElement();
            }
            w.WriteEndElement();
            w.Flush();
            w.Close();
        }
#endregion
        #region Public Data Request Functions
        public static List<IItem> GetItems(string text)
        {
            //Should use delegates for matching instead, oh well
            if (SMARTSEARCH)
            {
                return SmartGetItems(text);
            }
            else
            {
                return QuickGetItems(text);
            }
        }
        #region Get Items Modifiers
        private static List<IItem> SmartGetItems(string text)
        {
            StringBuilder rs = new StringBuilder(".*");
            foreach (char c in text.ToLower().ToCharArray())
            {
                if ((c == '.') || 
                    (c == '[') || 
                    (c == ']') ||
                    (c == '(') ||
                    (c == ')') || 
                    (c == '^') || 
                    (c == '$') || 
                    (c == '*') || 
                    (c == '?') ||
                    (c == '+')

                    )
                {
                    rs.Append("\\");
                }
                rs.Append(c.ToString());
                rs.Append(".*");
            }
            Regex txt = new Regex(rs.ToString());
            List<IItem> results = new List<IItem>();
            if (text != "")
            {
                if (currentIndex == index)
                {
                    SearchOn = true;
                    foreach (Alias a in AliasManager.AliasList)
                    {
                        if (a.DisplayName.ToLower() == text)
                        {
                            results.Insert(0, a);
                        }
                        else if (txt.IsMatch(a.DisplayName.ToLower()))
                        //else if (a.DisplayName.ToLower().Contains(text))
                        {
                            results.Add(a);
                        }
                    }
                }
                foreach (IItem item in currentIndex)
                {
                    if (SearchOn)
                    {
                        if (item.DisplayName.ToLower() == text)
                        {
                            results.Insert(0, item);
                        }
                        //else if (item.DisplayName.ToLower().Contains(text))
                        else if (txt.IsMatch(item.DisplayName.ToLower()))
                        {
                            results.Add(item);
                        }
                        if (results.Count > MATCHLIM)
                        {
                            break;
                        }
                    }
                    else
                    {
                        results.Add(item);
                    }
                }
                if (currentIndex == index)
                {
                    foreach (SystemWindow w in SystemWindow.FilterToplevelWindows(delegate(ManagedWinapi.Windows.SystemWindow c) { return ((/*c.Title.ToLower().Contains(text)*/txt.IsMatch(c.Title.ToLower())) && (c.Visible)); }))
                    {

                        results.Add(new SystemWindowItem(w.Title, w.HWnd, w.Process, w.ClassName));
                    }

                    if (Directory.Exists(PathFinder.FindPath(text)))
                    {
                        List<PathItem> tmp = new List<PathItem>();
                        if (text.EndsWith(":"))
                        {
                            text = text + "\\";
                        }
                        tmp.Add(new PathItem(PathFinder.FindPath(text), text));
                        results.Add(new ItemsList(tmp));
                    }
                    else if (File.Exists(text))
                    {
                        List<PathItem> tmp = new List<PathItem>();

                        tmp.Add(new PathItem(text, Path.GetFileNameWithoutExtension(text)));
                        results.Add(new ItemsList(tmp));
                    }
                    results.Add(new TextItem(text));
                }
            }
            else if (currentIndex != index)
            {
                return currentIndex;
            }


            return results;
        }
        private static List<IItem> QuickGetItems(string text)
        {
            List<IItem> results = new List<IItem>();
            if (text != "")
            {
                if (currentIndex == index)
                {
                    SearchOn = true;
                    foreach (Alias a in AliasManager.AliasList)
                    {
                        if (a.DisplayName.ToLower() == text)
                        {
                            results.Insert(0, a);
                        }
                        //else if (txt.IsMatch(a.DisplayName.ToLower()))
                        else if (a.DisplayName.ToLower().Contains(text))
                        {
                            results.Add(a);
                        }
                    }
                }
                foreach (IItem item in currentIndex)
                {
                    if (SearchOn)
                    {
                        if (item.DisplayName.ToLower() == text)
                        {
                            results.Insert(0, item);
                        }
                        else if (item.DisplayName.ToLower().Contains(text))
                        //else if (txt.IsMatch(item.DisplayName.ToLower()))
                        {
                            results.Add(item);
                        }
                        if (results.Count > MATCHLIM)
                        {
                            break;
                        }
                    }
                    else
                    {
                        results.Add(item);
                    }
                }
                if (currentIndex == index)
                {
                    foreach (SystemWindow w in SystemWindow.FilterToplevelWindows(delegate(ManagedWinapi.Windows.SystemWindow c) { return ((c.Title.ToLower().Contains(text)/*txt.IsMatch(c.Title.ToLower())*/) && (c.Visible)); }))
                    {

                        results.Add(new SystemWindowItem(w.Title, w.HWnd, w.Process, w.ClassName));
                    }

                    if (Directory.Exists(PathFinder.FindPath(text)))
                    {
                        List<PathItem> tmp = new List<PathItem>();
                        if (text.EndsWith(":"))
                        {
                            text = text + "\\";
                        }
                        tmp.Add(new PathItem(PathFinder.FindPath(text), text));
                        results.Add(new ItemsList(tmp));
                    }
                    else if (File.Exists(text))
                    {
                        List<PathItem> tmp = new List<PathItem>();

                        tmp.Add(new PathItem(text, Path.GetFileNameWithoutExtension(text)));
                        results.Add(new ItemsList(tmp));
                    }
                    results.Add(new TextItem(text));
                }
            }
            else if (currentIndex != index)
            {
                return currentIndex;
            }


            return results;
        }

        #endregion
        public static List<IItem> GetAllItems(string text)
        {
            if (currentIndex != index)
            {
                return currentIndex;
            }
            else
            {
                return GetItems(text);
            }
        }

        public static void ChangeItemAutoCompleteSource(ref TextBox cbItem, string type)
        {
            switch (type)
            {
                case "folder":
                    if (!(cbItem.AutoCompleteSource == AutoCompleteSource.FileSystemDirectories))
                    {
                        cbItem.AutoCompleteSource = AutoCompleteSource.FileSystemDirectories;
                        cbItem.AutoCompleteMode = AutoCompleteMode.SuggestAppend;
                        cbItem.SelectionStart = cbItem.Text.Length;
                        cbItem.SelectionLength = 0;
                    }
                    break;
                default:
                    if (!(cbItem.AutoCompleteSource == AutoCompleteSource.None))
                    {
                        cbItem.AutoCompleteSource = AutoCompleteSource.None;
                        cbItem.AutoCompleteMode = AutoCompleteMode.Suggest;
                        cbItem.SelectionStart = cbItem.Text.Length;
                        cbItem.SelectionLength = 0;
                    }
                    break;
            }
        }

        public static void ChangeParametersAutoCompleteSource(ref ComboBox cbParams, string pType, string iType)
        {
            switch (pType)
            {
                case "Path":
                    cbParams.DataSource = null;
                    cbParams.DropDownStyle = ComboBoxStyle.DropDown;
                    cbParams.AutoCompleteSource = AutoCompleteSource.FileSystemDirectories;
                    cbParams.AutoCompleteMode = AutoCompleteMode.SuggestAppend;
                    break;
                case "PathFiles":
                    cbParams.DataSource = null;
                    cbParams.DropDownStyle = ComboBoxStyle.DropDown;
                    cbParams.AutoCompleteSource = AutoCompleteSource.FileSystem;
                    cbParams.AutoCompleteMode = AutoCompleteMode.SuggestAppend;
                    break;
                case "URL":
                    cbParams.DataSource = null;
                    cbParams.DropDownStyle = ComboBoxStyle.DropDown;
                    cbParams.AutoCompleteSource = AutoCompleteSource.AllUrl;
                    cbParams.AutoCompleteMode = AutoCompleteMode.SuggestAppend;
                    break;
                case "SendTo":
                    cbParams.DropDownStyle = ComboBoxStyle.DropDownList;
                    cbParams.AutoCompleteSource = AutoCompleteSource.None;
                    //cbParams.DataSource = sendtolist;
                    cbParams.DisplayMember = "DisplayName";
                    cbParams.AutoCompleteMode = AutoCompleteMode.None;
                    break;
                case "OpenWith":
                    cbParams.DropDownStyle = ComboBoxStyle.DropDownList;
                    cbParams.AutoCompleteSource = AutoCompleteSource.None;
                    cbParams.DataSource = RegistryManager.GetOpenWithExes(iType);
                    cbParams.AutoCompleteMode = AutoCompleteMode.None;
                    break;
                case "CommandLine":
                    cbParams.DataSource = null;
                    cbParams.DropDownStyle = ComboBoxStyle.DropDown;
                    cbParams.AutoCompleteMode = AutoCompleteMode.SuggestAppend;
                    cbParams.AutoCompleteSource = AutoCompleteSource.CustomSource;
                    cbParams.AutoCompleteCustomSource = Params;
                    break;
                case "Unused":
                    cbParams.DataSource = null;
                    cbParams.DropDownStyle = ComboBoxStyle.DropDown;
                    cbParams.AutoCompleteMode = AutoCompleteMode.SuggestAppend;
                    cbParams.AutoCompleteSource = AutoCompleteSource.CustomSource;
                    cbParams.AutoCompleteCustomSource = Params;
                    break;
                default:
                    bool found = false;
                    foreach (IParametersProvider p in PluginManager.ParamProviders)
                    {
                        if (pType == p.ParameterType)
                        {
                            cbParams.DropDownStyle = ComboBoxStyle.DropDownList;
                            cbParams.AutoCompleteSource = AutoCompleteSource.None;
                            cbParams.AutoCompleteMode = AutoCompleteMode.None;
                            cbParams.DataSource = p.ParameterDataSource;
                            cbParams.DisplayMember = p.ParameterDisplayMember;
                            found = true;
                            break;
                        }
                    }
                    if (!found)
                    {
                        cbParams.DataSource = null;
                        cbParams.DropDownStyle = ComboBoxStyle.DropDown;
                        cbParams.AutoCompleteMode = AutoCompleteMode.SuggestAppend ;
                        cbParams.AutoCompleteSource = AutoCompleteSource.CustomSource;
                        cbParams.AutoCompleteCustomSource = Params;
                    }
                    break;
            }
        }

        public static void ReturnMainIndex()
        {
            currentIndex = index; 
            SearchOn = true;
            istack.PopAll();
            itstack.PopAll();
            sstack.PopAll();
             
        }

        public static bool SetSubIndex(IItem item, string itemtext, IAction action)
        {                
            List<IItem> tsindex = new List<IItem>();
            bool es = true;
            foreach (ISubIndex i in PluginManager.SubIndexes)
            {
                if (item.ItemType.ToLower() == i.ParentItemType.ToLower())
                {
                    tsindex.AddRange(i.GetSubIndex(item, action));
                    es = i.EnableSearch;
                }
            }

            if (tsindex.Count > 0)
            {
                SearchOn = es;
                currentIndex = tsindex;
                istack.Push(tsindex, es);
                itstack.Push(item);
                sstack.Push(itemtext);
                return true;
            }
            else
            {
                return false;
            }
        }

        public static void PreviousIndex()
        {
            if (currentIndex != index)
            {
                istack.Pop();
                itstack.Pop();
                sstack.Pop();
                currentIndex = istack.Top;
                SearchOn = istack.TopSearch;
            }
        }

        public static IItem ParentItem
        {
            get
            {
                return itstack.Top;
            }
        }
        
        public static string ParentText
        {
            get
            {
                return sstack.Top;
            }
        }

        #endregion
        #region SendTo

        //public static string GetSendToPath(string DisplayName)
        //{
        //    foreach (SendTo st in sendtolist)
        //    {
        //        if (st.DisplayName == DisplayName)
        //        {
        //            return st.Path;
        //        }
        //    }
        //    return DisplayName;
        //}

        //private static void CreateSendToList()
        //{
        //    string stpath = System.Environment.GetFolderPath(System.Environment.SpecialFolder.SendTo);
        //    string[] stfiles = Directory.GetFiles(stpath);
        //    sendtolist = new List<SendTo>();
        //    foreach (string s in stfiles)
        //    {
        //        sendtolist.Add(new SendTo(s, Path.GetFileNameWithoutExtension(s)));
        //    }
        //}

        #endregion
    }

    public class SendTo
    {
        private string path;
        private string dname;

        public string Path
        {
            get
            {
                return path;
            }
        
        }

        public string DisplayName
        {
            get
            {
                return dname;
            }
        }

        public SendTo(string Path, string DisplayName)
        {
            path = Path;
            dname = DisplayName;
        }
    }

    public class IndexStack
    {
        private LinkedList<bool> es;
        private LinkedList<List<IItem>> stack;
        public IndexStack(List<IItem> baseIndex)
        {
            stack = new LinkedList<List<IItem>>();
            stack.AddLast(baseIndex);
            es = new LinkedList<bool>();
            es.AddLast(true);
        }

        public List<IItem> Top
        {
            get
            {
                return stack.Last.Value;
            }
        }

        public bool TopSearch
        {
            get
            {
                return es.Last.Value;
            }
        }

        public List<IItem> Bottom
        {
            get
            {
                return stack.First.Value;
            }
        }

        public void Push(List<IItem> index, bool SearchOn)
        {
            stack.AddLast(index);
            es.AddLast(SearchOn);
        }

        public void Pop()
        {
            if (stack.Count > 1)
            {
                stack.RemoveLast();
                es.RemoveLast();
            }
        }

        public void PopAll()
        {
            while (stack.Count > 1)
            {
                stack.RemoveLast();
                es.RemoveLast();
            }
        }

        public void ResetBase(List<IItem> baseIndex)
        {
            stack.RemoveFirst();
            stack.AddFirst(baseIndex);
        }
    }

    public class ItemStack
    {
        private LinkedList<IItem> stack;
        public ItemStack()
        {
            stack = new LinkedList<IItem>();
            //stack.AddLast(baseIndex);
        }

        public IItem Top
        {
            get
            {
                try
                {
                    return stack.Last.Value;
                }
                catch{
                    return null;
                }
            }
        }

        public IItem Bottom
        {
            get
            {
                return stack.First.Value;
            }
        }

        public void Push(IItem item)
        {
            stack.AddLast(item);
        }

        public void Pop()
        {
            if (stack.Count > 0)
            {
                stack.RemoveLast();
            }
        }

        public void PopAll()
        {
            while (stack.Count > 0)
            {
                stack.RemoveLast();
            }
        }
    }
    public class StringStack
    {
        private LinkedList<string> stack;
        public StringStack()
        {
            stack = new LinkedList<string>();
            
        }

        public string Top
        {
            get
            {
                try
                {
                    return stack.Last.Value;
                }
                catch
                {
                    return "";
                }
            }
        }

        public string Bottom
        {
            get
            {
                return stack.First.Value;
            }
        }

        public void Push(string item)
        {
            stack.AddLast(item);
        }

        public void Pop()
        {
            if (stack.Count > 0)
            {
                stack.RemoveLast();
            }
        }

        public void PopAll()
        {
            while (stack.Count > 0)
            {
                stack.RemoveLast();
            }
        }
    }

}
